﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;

namespace WCFMastering.Client
{
    class Program
    {
        static void Main(string[] args)
        {
            //bool useHttp = false;
            //string endpointUrl = useHttp ? "http://localhost:8769/WCFMastering/OneWayService" : "net.tcp://localhost:8768/WCFMastering/OneWayService";
            //Binding binding = (useHttp ? (Binding)(new BasicHttpBinding()) : (Binding)(new NetTcpBinding()));
            //EndpointAddress endpointAddress = new EndpointAddress(endpointUrl);
            //WCFMasteringClient.OneWay.OneWayServiceClient onewayClient = new WCFMasteringClient.OneWay.OneWayServiceClient(binding, endpointAddress);
            //onewayClient.MethodWithError();
            //try
            //{
            //    onewayClient.MethodWithOutError();
            //    Console.WriteLine("No exception");
            //    onewayClient.Close();
            //}
            //catch (Exception e)
            //{
            //    Console.WriteLine(e.Message);
            //}

            #region old code

            //bool exsit = QueryAddressForContract("http://localhost:8000/WCFMastering/ISimpleCalculator", typeof(WCFMastering.Contracts.ISimpleCalculator));
            //Console.WriteLine(exsit);

            //IEnumerable<ServiceEndpoint> allEndpoints = MetadataResolver.Resolve(typeof(WCFMastering.Contracts.ISimpleCalculator),
            //    new EndpointAddress("http://localhost:8000/WCFMastering/ISimpleCalculator?wsdl"));
            //exsit = allEndpoints.Count() > 0;
            //Console.WriteLine(exsit);

            //using (WCFMasteringClient.SimpleCalculatorClient proxy = new WCFMasteringClient.SimpleCalculatorClient())
            //{
            //    var addIntResult = proxy.AddInt(1, 2);
            //    var addDoubleResult = proxy.AddDouble(1, 2.3);

            //}

            //using (WCFMasteringClient.Scientific.ScientificCalculatorClient client = new WCFMasteringClient.Scientific.ScientificCalculatorClient())
            //{
            //}

            //using (ChannelFactory<WCFMastering.Contracts.ISimpleCalculator> channelFactory = new ChannelFactory<Contracts.ISimpleCalculator>())
            //{
            //    var client = channelFactory.CreateChannel();
            //    client.Add(1, 2);
            //}

            #endregion

            WCFMasteringClient.DuplexService.IDuplexServiceCallback duplexCallback = new InnerDuplexServiceCallback();
            InstanceContext instanceContext =new InstanceContext (duplexCallback);
            WCFMasteringClient.DuplexService.DuplexServiceClient duplexServiceClient = new WCFMasteringClient.DuplexService.DuplexServiceClient(instanceContext);
            duplexServiceClient.DoSomeThing();

            // Using Generic DuplexClientBase<T,C>
            //WCFMastering.Framework.InstanceContext<WCFMastering.Contracts.IDuplexServiceCallback> callbackContext = new Framework.InstanceContext<Contracts.IDuplexServiceCallback>(new WCFMastering.Client.GenericDuplexServiceCallback());
            //WCFMastering.Client.GenericDuplexServiceClient genericDuplexClient = new GenericDuplexServiceClient(callbackContext);

            Console.WriteLine("Input any key to exit!");
            Console.ReadKey();
        }

        static bool QueryAddressForContract(string address , Type contractType)
        {
            Uri addressUri =new Uri (address+"?wsdl");
            MetadataExchangeClient client = new MetadataExchangeClient(addressUri, MetadataExchangeClientMode.HttpGet);
            MetadataSet metadataSet = client.GetMetadata();
            WsdlImporter importor = new WsdlImporter(metadataSet);
            ServiceEndpointCollection endPointCollection = importor.ImportAllEndpoints();
            ContractDescription contractDescription = ContractDescription.GetContract(contractType);
            return endPointCollection.Any(endPoint => 
                    endPoint.Contract.Name == contractDescription.Name 
                    &&endPoint.Contract.Namespace == contractDescription.Namespace);
        }
    }

    public class InnerDuplexServiceCallback : WCFMasteringClient.DuplexService.IDuplexServiceCallback
    {
        #region IDuplexServiceCallback Members

        public void OnCallback()
        {
            Console.WriteLine("Call back success!");
        }

        #endregion
    }

    public class MyDuplexServiceClient :WCFMasteringClient.DuplexService.DuplexServiceClient, WCFMasteringClient.DuplexService.IDuplexServiceCallback
    {
        public MyDuplexServiceClient(InstanceContext callbackInstanceContext)
            : base(callbackInstanceContext)
        { 
        }

        WCFMasteringClient.DuplexService.DuplexServiceClient duplexServiceClient;

        public void CallService(Action<WCFMasteringClient.DuplexService.DuplexServiceClient> duplexServiceAction)
        {
            InstanceContext callbackInstanceContext = new InstanceContext(this);
            duplexServiceClient = new WCFMasteringClient.DuplexService.DuplexServiceClient(callbackInstanceContext);
            duplexServiceAction(duplexServiceClient);
        }

        public void Dispose()
        {
            if (duplexServiceClient != null)
            {
                duplexServiceClient.Close();
            }
        }

        #region IDuplexServiceCallback Members

        public void OnCallback()
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}
